package main

import (
	"chapter4/expoftime"
	"fmt"
	"math"
	"math/rand"
	"sort"
)

type Circle struct { //定义一个圆形的结构体
	R float64
}

func NewCircle(r float64) *Circle { //定义一个圆形的构造函数
	return &Circle{R: r}
}

func (c *Circle) AreaC() (a float64) { //定义圆形的计算面积方法
	a = math.Pow(c.R, 2) * 3.1415926
	return a
}

type Triangle struct { //定义一个三角形的结构体
	A float64
	H float64
}

func NewTriangle(a, h float64) *Triangle { //定义一个三角形的构造函数
	return &Triangle{A: a, H: h}
}

func (t *Triangle) AreaT() (a float64) { //定义一个三角形面积计算方法，底乘高除以二
	a = (t.A * t.H) / 2
	return a
}

type Rectangle struct { //定义一个长方形的结构体
	Ls float64
	Ss float64
}

func NewRectangle(ls, ss float64) *Rectangle { //定义一个长方形的构造函数
	return &Rectangle{Ls: ls, Ss: ss}
}

func (r *Rectangle) AreaR() (a float64) { //定义一个长方形的面积计算方法
	a = r.Ls * r.Ss
	return
}

// 构建一个形状生成器，包含形状的参数，当生成的形状什么类型都有时，循环退出，将生成的形状参数放入对应类型的切片中，返回切片的指针
func shape(max, min float64) (cir *[]Circle, tri *[]Triangle, rec *[]Rectangle) {
	var ri int
	var c = make([]Circle, 0)
	var t = make([]Triangle, 0)
	var r = make([]Rectangle, 0)
	for i := 0; ; i++ {
		if len(c)*len(t)*len(r) >= 1 {
			break
		}
		ri = rand.Intn(3)
		if ri == 0 {
			rr := rand.Float64()*(max-min) + min
			c = append(c, *NewCircle(rr))
		} else if ri == 1 {
			ta := rand.Float64()*(max-min) + min
			th := rand.Float64()*(max-min) + min
			t = append(t, *NewTriangle(ta, th))
		} else if ri == 2 {
			rs1 := rand.Float64()*(max-min) + min
			rs2 := rand.Float64()*(max-min) + min
			if rs1 >= rs2 {
				r = append(r, *NewRectangle(rs1, rs2))
			} else {
				r = append(r, *NewRectangle(rs2, rs1))
			}
		}
	}
	cir = &c
	tri = &t
	rec = &r
	return
}

// 定义新的结构体类型，准备用来排序
type MapArea struct {
	SP string
	AR float64
}

// 定义构造函数
func NewMapArea(sp string, ar float64) *MapArea {
	return &MapArea{SP: sp, AR: ar}
}

// 定义新类型，切片用来存入形状和对应面积，切片的每一个元素是一个MapArea结构体
type MapAreaSlice []MapArea

// 定义用来排序的数据的函数
func MASSort(cir *[]Circle, tri *[]Triangle, rec *[]Rectangle) *MapAreaSlice {
	var m1 = make(map[string]float64, len(*cir)+len(*tri)+len(*rec))
	var k string
	var mas = make(MapAreaSlice, 0, len(m1))
	//将计算后的形状及对应的面积录入map中
	for i, v := range *cir {
		k = fmt.Sprintf("%s%d", "circle", i+1)
		m1[k] = v.AreaC()
	}
	for i, v := range *tri {
		k = fmt.Sprintf("%s%d", "triangle", i+1)
		m1[k] = v.AreaT()
	}
	for i, v := range *rec {
		k = fmt.Sprintf("%s%d", "rectangle", i+1)
		m1[k] = v.AreaR()
	}
	//将map序列化
	for i, v := range m1 {
		mas = append(mas, *NewMapArea(i, v))
	}
	return &mas
}

//上面是1、2题

var fibm = make(map[int]int)

func fib(n int) int {
	if n <= 0 {
		panic("n is neg")
	} else if n < 3 {
		fibm[n] = 1
		return fibm[n]
	}
	fibm[n] = fib(n-1) + fib(n-2)
	return fibm[n]
}

//上面是第3题

func main() {
	cIr, tRi, rEc := shape(10, 5) //这里定义数据最大值为10，最小值为5，即为圆时半径半径范围为5-10，其余形状以此类推
	m := *MASSort(cIr, tRi, rEc)
	//排序计算出面积后的切片元素
	sort.Slice(m, func(i, j int) bool {
		return m[i].AR > m[j].AR
	})
	//打印排序后的结果
	for i := 0; i < len(m); i++ {
		fmt.Printf("形状：%s,     面积：%.2f\n", m[i].SP, m[i].AR)
	}
	//上面是1、2题
	fmt.Println(fib(10))
	fmt.Println(fibm)
	//上面是第3题

	//第四题

	//生成8年前的今天时间9点30分
	fmt.Println(expoftime.Bfeight())
	//4.1毫秒时间戳,为Unix时间的时间戳，非本地
	fmt.Println(expoftime.Needstamp())
	//4.2格式化输出
	fmt.Println(expoftime.BfeightFormat(expoftime.Bfeight()))
	//4.3周几，过了多少周
	expoftime.Needweekday(expoftime.Bfeight())
	//4.4距离今天的天数
	fmt.Printf("距离今天已经过了%.2f天\n", expoftime.Tonowday(expoftime.Bfeight()))
	//fmt.Println(expoftime.Test())
}
